package com.eryos.android.cigarettecounter;

import java.util.TreeSet;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.Toast;

import com.eryos.android.cigarettecounter.beans.History;
import com.eryos.android.cigarettecounter.database.CigaretteDatabase;
import com.eryos.android.cigarettecounter.tool.GoogleAnalyticsProvider;
import com.eryos.android.cigarettecounter.ui.Credits;
import com.google.ads.AdRequest;
import com.google.ads.AdSize;
import com.google.ads.AdView;

/**
 * Project : CigaretteCounter Author : Olivier Combe URL :
 * http://eryos.fr/CigaretteCounter/
 * 
 * Copyright(C)2011 - Olivier Combe
 * 
 * Licensed under the Apache License, Version 2.0(the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 * 
 * @version \$Revision.*\$
 * @author Olivier Combe
 */
public abstract class RootActivity extends Activity {

	/** *************** Static Variables. *************** **/
	protected String LOG_TAG = "RootActivity";

	/** Config filename. */
	public static final String PREFS_NAME = "eryos-config";
	/** Output filename. */
	public static final String SDCARD_NAME = "cigarettecounter.csv";

	/** Current database. */
	protected static CigaretteDatabase db;

	/** Ads ID. */
	private static final String MY_AD_UNIT_ID = "a14d256d9745ea0";

	private AdView adView; // = new AdView(this, AdSize.BANNER, MY_AD_UNIT_ID);

	private static CigaretteCounter home;
	private static ProgressDialog waitingDialog;
	private static View rootView = null;

	/** *************** Instance Variables. *************** **/
	protected Menu menu;

	/**
	 * Different types of Historical.
	 */
	public enum HISTO {
		/** Weekly histo. */
		WEEKLY,
		/** Monthly Histo. */
		MONTHLY
	};

	/**
	 * List of views in the application.
	 */
	public enum VIEW {
		/** Home page. */
		HOME,
		/** Weekly charts page. */
		WEEKLY,
		/** Monthly charts page. */
		MONTHLY,
		/** Settings page. */
		SETTINGS,
		/** Credits page. */
		CREDITS
	};

	private final Handler mHandler = new Handler();

	private final Runnable initValuesComplete = new Runnable() {
		@Override
		public void run() {
			/* Update the UI with values retrieved/calculated by initValues() */
			updateUI();

			/* dismiss the splash screen created after initUI() */
			hideWaitingMessageAfterLoad();
		}
	};

	/**
	 * @return the default LOG_TAG.
	 */
	protected String getLogTag() {
		return LOG_TAG;
	}

	/**
	 * Hide the 'Waiting' popup.
	 */
	public void hideWaitingMessageAfterLoad() {
		Log.d(LOG_TAG, "hideWaitingMessageAfterLoad");
		hideWaitingMessage();
	}

	/** *************** *********** *************** **/

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void onCreate(final Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		LOG_TAG = getLocalClassName();
		Log.d(LOG_TAG, "onCreate");

		if (this instanceof CigaretteCounter) {
			if (rootView == null) {
				rootView = getWindow().getDecorView();
			}
			if (home != null) {
				home.finish();
			} else {
				// 1ere ouverture de Home
				Log.i(LOG_TAG,
						"######################################################");
				Log.i(LOG_TAG, "Start Eryos - CigaretteCounter");
				Log.i(LOG_TAG,
						"App Version : "
								+ getResources().getString(R.string.version));
				Log.i(LOG_TAG,
						"App Build : "
								+ getResources().getString(R.string.build));
				Log.i(LOG_TAG,
						"######################################################");
			}

			home = (CigaretteCounter) this;
		}

		/* Init UI elements */
		initUI();

		/* show splashscreen during complex treatment */
		showWaitingMessage();

		/* Init Ads */
		// initAds();

		/* Init Analytics Tracker */
		// initTracker();

		/* Init and open the DB connection */
		initDB();

		/* Init UI Handlers */
		initHandlers();

		/* Process long/complex treatments in separate thread */
		Thread t = new Thread() {
			@Override
			public void run() {
				/* Init values(from DB, Network, etc.) */
				initValues();

				/* stop this thread and return to the main thread */
				mHandler.post(initValuesComplete);
			}
		};
		t.start();

	}

	/**
	 * Method used to initialize the DB connection.
	 */
	private void initDB() {
		if (db == null) {
			db = CigaretteDatabase.getInstance(this);
			db.open();
		}
	}

	/**
	 * Method used to handle Ads part.
	 */
	private void initAds() {
		boolean showAd = true;

		if (showAd) {
			Log.i(LOG_TAG, "AdMob Initializing");
			adView = getAdView(this);

			// Lookup your LinearLayout
			LinearLayout layout;
			try {
				layout = (LinearLayout) findViewById(R.id.main_layout);

				// Add the adView to it
				layout.addView(adView);
			} catch (Exception e) {
				Log.e(LOG_TAG, "initAds", e);
			}

		}
	}

	/**
	 * Get the Ad View.
	 * 
	 * @param activityArg
	 *            which request the add.
	 * @return an ad.
	 */
	public static AdView getAdView(final Activity activityArg) {
		Log.i("AdView", "AdView Initializing");
		Activity activity = activityArg;

		if (activity == null) {
			Log.w("AdView", "Null Activity, using root Activity");

			activity = home;
		}
		if (activity != null) {
			// Create the adView
			AdView newAdView = new AdView(activity, AdSize.BANNER,
					MY_AD_UNIT_ID);

			// To get test ads on this device, call
			AdRequest adRequest = new AdRequest();
			adRequest.addTestDevice(AdRequest.TEST_EMULATOR);
			// adRequest.setLocation(location);
			TreeSet<String> keywords = new TreeSet<String>();
			keywords.add("smoke");
			keywords.add("geek");
			keywords.add("cigarette");
			keywords.add("smoking");
			adRequest.setKeywords(keywords);

			// Initiate a generic request to load it with an ad
			newAdView.loadAd(adRequest);

			Log.d("AdView", "Ad found !!!");
			return newAdView;
		}

		Log.w("AdView", "Null Activity passed in param");
		return null;
	}

	/**
	 * Method used to handle Tracker.
	 */
	private void initTracker() {
		Log.i(LOG_TAG, "GoogleAnalytics : Init Tracker");
		GoogleAnalyticsProvider.startTracker(this);
		GoogleAnalyticsProvider.trackCustomVars();
		GoogleAnalyticsProvider.trackPage(LOG_TAG);
		GoogleAnalyticsProvider.dispatch();
	}

	/**
	 * Init all UI elements.
	 */
	protected abstract void initUI();

	/**
	 * Method used to defined all UI handlers.
	 */
	protected abstract void initHandlers();

	/**
	 * init Values(not UI)for this activiry from DB / Network / etc.
	 */
	protected abstract void initValues();

	/**
	 * Method used to update the UI after called to initValues().
	 */
	public abstract void updateUI();

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean onCreateOptionsMenu(final Menu menuArg) {
		this.menu = menuArg;
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.options_menu, menu);

		return true;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean onOptionsItemSelected(final MenuItem item) {
		switch (item.getItemId()) {
		case R.id.home:
			showView(VIEW.HOME);
			return true;
		case R.id.param:
			showView(VIEW.SETTINGS);
			return true;
		case R.id.credits:
			showView(VIEW.CREDITS);
			return true;
		default:
			return false;
		}
	}

	/**
	 * Method used to display another view(Home, Stats, Settings).
	 * 
	 * @param viewArg
	 *            : the new view to display
	 */
	public void showView(final VIEW viewArg) {
		/* Show splash screen */
		showWaitingMessage();

		Class<? extends RootActivity> dest = this.getClass();
		History typeHisto = new History(History.Type.WEEKLY);
		boolean createActitivy = true;
		switch (viewArg) {
		case HOME:
			dest = CigaretteCounter.class;
			break;
		case WEEKLY:
			dest = HistoryActivity.class;
			typeHisto = new History(History.Type.WEEKLY);
			break;
		case MONTHLY:
			dest = HistoryActivity.class;
			typeHisto = new History(History.Type.MONTHLY);
			break;
		case SETTINGS:
			dest = ConfigActivity.class;
			break;
		case CREDITS:
			hideWaitingMessage();
			createActitivy = false;
			new Credits(this);
			break;
		default:
			break;
		}

		if (createActitivy) {
			Intent intent = new Intent(RootActivity.this, dest);
			intent.putExtra(History.class.toString(), typeHisto);
			startActivity(intent);

			if (!(this instanceof CigaretteCounter)) {
				finish();
			}
		}
	}

	@Override
	public void onResume() {
		super.onResume();
		/* Init Ads */
		initAds();

		/* Init Analytics Tracker */
		initTracker();

		Log.d(getLocalClassName(), "onResume");
		db.open();
	}

	@Override
	public void onStart() {
		super.onStart();
		Log.d(getLocalClassName(), "onStart");
		db.open();
	}

	@Override
	public void onRestart() {
		super.onRestart();
		Log.d(getLocalClassName(), "onRestart");
		db.open();

		initTracker();

		/* show splashscreen during complex treatment */
		showWaitingMessage();

		/* Process long/complex treatments in separate thread */
		Thread t = new Thread() {
			@Override
			public void run() {
				/* Init values(from DB, Network, etc.) */
				initValues();

				/* stop this thread and return to the main thread */
				mHandler.post(initValuesComplete);
			}
		};
		t.start();

	}

	@Override
	protected void onDestroy() {
		if (adView != null) {
			adView.destroy();
		}
		super.onDestroy();
		Log.d(getLocalClassName(), "onDestroy");
		hideWaitingMessage();
		GoogleAnalyticsProvider.stopTracker();
	}

	@Override
	protected void onPause() {
		super.onPause();
		Log.d(getLocalClassName(), "onPause");
		hideWaitingMessage();
		// GoogleAnalyticsProvider.stopTracker();
	}

	@Override
	protected void onStop() {
		super.onStop();
		Log.d(getLocalClassName(), "onStop");
	}

	/**
	 * @return the Root Context
	 */
	public Context getRootContext() {
		Context ctx;
		// Decor View
		ctx = getWindow().getContext();
		// ctx = getWindow().getDecorView().getRootView().getContext();
		// ctx = getWindow().getDecorView().getContext();

		return ctx;
	}

	/**
	 * Show a waiting popup.
	 */
	public void showWaitingMessage() {
		try {
			Log.d(getLocalClassName(), "show waiting message : "
					+ waitingDialog);
			waitingDialog = new ProgressDialog(getRootContext());
			waitingDialog.setMessage(getResources().getString(
					R.string.home_waiting));
			waitingDialog.setIndeterminate(true);
			waitingDialog.setCancelable(false);
			waitingDialog.show();
		} catch (IllegalStateException e) {
			try {
				waitingDialog = new ProgressDialog(this);
				waitingDialog.setMessage(getResources().getString(
						R.string.home_waiting));
				waitingDialog.setIndeterminate(true);
				waitingDialog.setCancelable(false);
				waitingDialog.show();
			} catch (Exception e1) {
				Log.e(getLocalClassName(), "showWaitingMessage 2 : Error : ",
						e1);
			}
		} catch (Exception e) {
			Log.e(getLocalClassName(), "showWaitingMessage : Error : ", e);
		}
	}

	/**
	 * hide the waiting popup.
	 */
	public void hideWaitingMessage() {
		try {
			if (waitingDialog != null) {
				Log.d(getLocalClassName(), "dismiss waiting message : "
						+ waitingDialog);
				waitingDialog.dismiss();
				waitingDialog.cancel();
				waitingDialog = null;
			}
		} catch (Exception e) {
			Log.e(getLocalClassName(), "hideWaitingMessage : Error : ", e);
		}
	}

	/**
	 * Hide the waiting popup and show a Toast with argument value.
	 * 
	 * @param id
	 *            of the text
	 */
	public void hideWaitingMessage(final int id) {
		hideWaitingMessage();
		Toast.makeText(this, id, Toast.LENGTH_SHORT).show();
	}

	/**
	 * Hide the 'Waiting' popup and show a Toast.
	 * 
	 * @param text
	 *            to set in the toast
	 */
	public void hideWaitingMessage(final String text) {
		hideWaitingMessage();
		Toast.makeText(this, text, Toast.LENGTH_LONG).show();
	}

	/**
	 * Check if the network is available or not.
	 * 
	 * @return true if the network is available
	 */
	protected boolean isNetworkAvailable() {
		ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo activeNetworkInfo = connectivityManager
				.getActiveNetworkInfo();
		return activeNetworkInfo != null && activeNetworkInfo.isConnected();
	}

}
